uniform float gTime;

struct VS_IN
{
	float3 posL     : POSITION;
	float2 texcoord : TEXCOORD0;
};

struct VS_OUT
{
	float4 posH     : SV_POSITION;
	float2 texcoord : TEXCOORD0;
};
 
VS_OUT VS(VS_IN vIn)
{
	VS_OUT vOut;
	vOut.posH = float4(vIn.posL, 1.0f);
	vOut.texcoord = vIn.texcoord;
	return vOut;
}

#define NO_INTERSECTION 9999999.0f
#define EPS             0.0001f

float distSphere(float3 p, float4 sphere)
{
	return distance(p, sphere.xyz) - sphere.w;
}

float raySphereIntersect(float3 rayPos, float3 rayDir, float4 sphere)
{
	float t = NO_INTERSECTION;
	
	float3 dist = rayPos - sphere.xyz;
	float B = dot(dist, rayDir);
	float C = dot(dist, dist) - sphere.w * sphere.w;
	float delta = B*B - C;
	if(delta > 0.0f)
	{
		t = - B - sqrt(delta);
	}	
	return t;
}

float4 rayTracing(VS_OUT vIn)
{
	float x = vIn.texcoord.x * 1.33333333f;
	float y = vIn.texcoord.y;
	
	float3 rayOrig = float3(0.0f, 0.0f, 0.0f);
	float3 rayDir = float3(x, y, 2.0f);
	rayDir = normalize(rayDir);
	
	float4 sphere1 = float4(0.0f, 0.0f, 5.0f, 1.0f);
	if(raySphereIntersect(rayOrig, rayDir, sphere1) != NO_INTERSECTION)
		return float4(0.0f, 0.0f, 0.0f, 1.0f);

	return float4(1.0f, 0.0f, 1.0f, 1.0f);
}

#define MAX_ITER_VISUALIZE 64.0f

float3 numIterVis(float numIter)
{
	float QUARTER = MAX_ITER_VISUALIZE * 0.25f;
	float HALF = MAX_ITER_VISUALIZE * 0.5f;
	
	float B = lerp(0.5f, 0.0f, numIter / QUARTER);
	float G ;//= lerp(1.0f, 0.0f, abs(numIter - QUARTER) / QUARTER);
	if(numIter < HALF)
		G = lerp(0.0f, 1.0f, numIter / QUARTER);
	else
		G = lerp(1.0f, 0.0f, (numIter - HALF) / HALF);
	float R = lerp(0.0f, 1.0f, (numIter - QUARTER) / QUARTER);
	//float a = numIter / 50.0f;
	return float3(R, G, B);
}

float4 rayMarching(VS_OUT vIn)
{
	float x = vIn.texcoord.x * 1.33333333f;
	float y = vIn.texcoord.y;
	
	float3 rayOrig = float3(0.0f, 0.0f, 0.0f);
	float3 rayDir = float3(x, y, 2.0f);
	rayDir = normalize(rayDir);
	
	float4 sphere1 = float4(0.0f, 0.0f, 5.0f, 1.0f);
	
	float3 currPos = rayOrig;
	float numIter = 0;
	while(distance(currPos, rayOrig) < 100.0f)
	{
		numIter += 1.0f;
		float dist = distSphere(currPos, sphere1);
		if(dist < EPS)
			break;
		currPos += rayDir * dist;
	}
	
	return float4(numIterVis(numIter), 1.0f);
}

float4 PS(VS_OUT pIn) : SV_Target
{
	float x = pIn.texcoord.x * 0.5f + 0.5f;
	float y = pIn.texcoord.y * 0.5f + 0.5f;
	
	
	return float4(saturate(abs(sin(gTime)) * y * y * y / x),
		saturate(abs(sin(gTime)) * x * x * x / y),
		saturate(abs(sin(gTime))),
		1.0f);
	
	
	//return rayMarching(pIn);
		
	
	/*	
	return float4
	(
		saturate(x),
		0.0f,
		0.0f,
		1.0f
	);
	*/
}

technique11 Layout
{
	pass P0
	{
		SetVertexShader( CompileShader( vs_5_0, VS() ) );
		SetGeometryShader( NULL );
		SetPixelShader( CompileShader( ps_5_0, PS() ) );
	}
}
